<template>
	<div :class="classNames">
		<template v-if="mode === 'STYLE2'">
			<div :class="`${baseClass}__content`">
				<AppGrid
					:items="data"
					:columns="getColumns()"
					:localMode="true"
					@add-item="add"
					@remove-item="(item: any, index: number) => remove(index)"
				>
					<template
						v-for="slotKey of slotKeys"
						v-slot:[slotKey]="{ column, text, record, index }"
					>
						<slot
							:name="slotKey"
							:data="record"
							:context="context"
							:viewParams="viewParams"
							:handleComponentAction="(controller: any, actionParam: IParam) => handleComponentAction(controller, actionParam, index)"
						></slot>
					</template>
				</AppGrid>
			</div>
		</template>
		<template v-else>
			<div
				:class="`${baseClass}__header`"
				v-show="!(mode === 'STYLE3' && data.length >= 1)"
			>
				<span class="repeater-caption" v-if="showCaption && caption">
					{{ caption }}
				</span>
				<AppButton
					type="primary"
					class="repeater-add"
					size="small"
					shape="circle"
					:isDebounce="false"
					@click="add"
				>
					<template #icon>
						<PlusOutlined />
					</template>
				</AppButton>
			</div>
			<div :class="`${baseClass}__content`">
				<template v-for="(item, vIndex) of data">
					<AppRow :class="`${baseClass}__item`" :layoutOpts="layoutOpts">
						<AppButton
							type="error"
							class="repeater-remove"
							size="small"
							shape="circle"
							:isDebounce="false"
							@click="remove(vIndex)"
						>
							<template #icon>
								<DeleteOutlined />
							</template>
						</AppButton>
						<slot
							:data="item"
							:context="context"
							:viewParams="viewParams"
							:handleComponentAction="(controller: any, actionParam: IParam) => handleComponentAction(controller, actionParam, vIndex)"
						></slot>
					</AppRow>
				</template>
			</div>
		</template>
	</div>
</template>
<script lang="ts" setup>
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { IContext, IEvent, IParam, ILayoutOpts } from '@/core';
import { AppRow } from '@/components/common/row';
import { AppButton } from '@components/common/button';
import { AppGrid } from '@components/widgets/grid';

interface Props {
	caption: string;
	context: IContext;
	viewParams: IParam;
	name: string;
	parentData: IParam;
	level?: number;
	mode?: 'DEFAULT' | 'STYLE2' | 'STYLE3';
	showCaption?: boolean;
	children?: IParam;
	columnAlign?: 'center' | 'left' | 'right';
	layoutOpts: ILayoutOpts;
}
const props = withDefaults(defineProps<Props>(), {
	level: 0,
	mode: 'DEFAULT',
	showCaption: true,
	columnAlign: 'center',
});
type eventType =
	| 'componentInit'
	| 'valueChange'
	| 'mdCtrlDataSave'
	| 'mdCtrlUpdateDefault'
	| 'mdCtrlCreateDefault';
const emit = defineEmits<{
	(name: 'component-action', value: IEvent<eventType>): void;
}>();
//  基础类名
const baseClass = 'app-form-mdctrl-repeater';

const classNames = computed(() => {
	return {
		[baseClass]: true,
		[`${baseClass}--${props.name.toLowerCase()}`]: true,
		[`${baseClass}--${props.mode.toLowerCase()}`]: true,
		[`${baseClass}--level-${props.level}`]: true,
	};
});
const slotKeys = computed<string[]>(() => {
	return Object.keys(useSlots()) || [];
});

const data = ref<IParam[]>([]);

watch(
	() => props.parentData,
	() => {
		const { parentData, name } = props;
		if (parentData && name && parentData[name] && parentData[name].length > 0) {
			data.value = parentData[name];
		} else {
			data.value = [];
		}
	},
	{ deep: true, immediate: true }
);

const executeFormDetail = ({ name, action, data: value }: IEvent<string>) => {
	switch (action) {
		case 'load':
			handleUpdateDefault(props.name, data.value);
			valueChange();
			break;
		case 'beforeSave':
			repeaterSaved();
			break;
		case 'add':
			add();
			break;
		case 'remove':
			remove(value);
			break;
	}
};

const add = () => {
	const item: IParam = {};
	handleCreateDefault(props.name, item);
	data.value.push(item);
	valueChange();
};

const remove = (index: number) => {
	data.value.splice(index, 1);
	valueChange();
};

const init = () => {
	emit('component-action', {
		name: props.name,
		action: 'componentInit',
		data: { executeFormDetail },
	});
};

init();

const repeaterSaved = () => {
	emit('component-action', {
		name: props.name,
		action: 'mdCtrlDataSave',
		data: { type: 'MDCTRL', name: props.name },
	});
};

const handleComponentAction = (
	controller: any,
	actionParam: IParam,
	vIndex: number
) => {
	const { action, data: value, name } = actionParam;
	switch (action) {
		case 'valueChange':
			handleChildValueChange(name, value, vIndex);
			break;
		case 'mdCtrlCreateDefault':
			handleCreateDefault(name, value);
			break;
		case 'mdCtrlUpdateDefault':
			handleUpdateDefault(name, value);
			break;
	}
};

const valueChange = () => {
	emit('component-action', {
		name: props.name,
		action: 'valueChange',
		data: data.value,
	});
};

const handleChildValueChange = (name: string, value: any, vIndex: number) => {
	if (!name) {
		return;
	}
	data.value[vIndex][name] = value;
	emit('component-action', {
		name: name,
		action: 'valueChange',
		data: value,
	});
	valueChange();
};

const getColumns = () => {
	const { children, columnAlign } = props;
	const columns: IParam[] = [];
	if (children && children.length > 0) {
		children.forEach((item: IParam) => {
			columns.push({
				align: columnAlign,
				codeName: item.name,
				dataIndex: item.name,
				caption: item.caption,
				width: 150,
				show: true,
			});
		});
	}
	return columns;
};

const handleCreateDefault = (name: string, item: IParam) => {
	emit('component-action', {
		name: name,
		action: 'mdCtrlCreateDefault',
		data: item,
	});
};

const handleUpdateDefault = (name: string, data: IParam[]) => {
	emit('component-action', {
		name: name,
		action: 'mdCtrlUpdateDefault',
		data: data,
	});
};
</script>
